home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 7
/
FM Towns Free Software Collection 7.iso
/
t_os
/
cal
/
cal.c
next >
Wrap
C/C++ Source or Header
|
1993-11-30
|
18KB
|
800 lines
/* 1992.10.3 守屋一成(morip)作 */
/* 1993.6.27 一部変更 */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
double analyze(char[],int *);
double takevalue(char[],int *,int *);
double pai(int,int,char[],int *);
double sigma(int,int,char[],int *);
double sinc(double);
double pulse(double);
double biterm(char[],double,int *,int,int *);
double triangle(double);
int next(char[],int),level(char);
unsigned prtcpy(char[],int,int);
unsigned spacefilter(char[]);
void itoa(int,char[],int);
int ssp;
void itoa(int inp,char oup[],int base)
{
double id,bd,a;
int len,i,b;
char tmp[10];
id=(double)inp;
bd=(double)base;
a=floor(id/bd);
b=(int)(id-a*bd);
tmp[0]='\0';
while(a>0.0){
switch(b){
case 0:strcat(tmp,"0"); break;
case 1:strcat(tmp,"1"); break;
case 2:strcat(tmp,"2"); break;
case 3:strcat(tmp,"3"); break;
case 4:strcat(tmp,"4"); break;
case 5:strcat(tmp,"5"); break;
case 6:strcat(tmp,"6"); break;
case 7:strcat(tmp,"7"); break;
case 8:strcat(tmp,"8"); break;
case 9:strcat(tmp,"9"); break;
}
id=a;
a=floor(id/bd);
b=(int)(id-a*bd);
}
switch(b){
case 0:strcat(tmp,"0"); break;
case 1:strcat(tmp,"1"); break;
case 2:strcat(tmp,"2"); break;
case 3:strcat(tmp,"3"); break;
case 4:strcat(tmp,"4"); break;
case 5:strcat(tmp,"5"); break;
case 6:strcat(tmp,"6"); break;
case 7:strcat(tmp,"7"); break;
case 8:strcat(tmp,"8"); break;
case 9:strcat(tmp,"9"); break;
}
len=strlen(tmp);
for(i=0;i<=len-1;i++){
oup[i]=tmp[len-1-i];
}
oup[len]='\0';
}
unsigned spacefilter(char expression[]) /* スペースを取除く */
{
int i,j;
char c,ext[256];
i=0;
j=0;
c=expression[j];
while(c!='\0'){
while(c==' '){
j++;
c=expression[j];
}
ext[i]=c;
i++;
j++;
c=expression[j];
}
ext[i]='\0';
return((unsigned)ext);
}
unsigned prtcpy(char expression[],int start,int end) /* startからendまでの文字列を取り出す */
{
char extract[256];
int k;
for(k=0;k<=end-start;k++){
extract[k]=expression[k+start];
}
extract[k]='\0';
return((unsigned)extract);
}
int next(char expression[],int i) /* ”(”に対応する”)”の位置を検出する */
{
char c;
c=expression[i];
while(c!=')'){
i++;
if(c=='('){
i=next(expression,i);
i++;
}
c=expression[i];
}
return(i);
}
double pai(int start,int end,char expression[],int *err) /* Π(総積) */
{
double a;
int i,j,k,l,len;
char c,argument,extract[256],number[10];
if(start>end){
printf("Error! Start value larger than end value");
exit(0);
}
ssp++; /* ネスティングの回数 */
argument=(char)('a'+ssp-1);
strcpy(extract,expression);
a=1.0;
for(i=start;i<=end;i++){
itoa(i,number,10);
k=0;
len=strlen(extract);
if(len==0){
printf("Error! Illeagal parameter");
exit(4);
}
for(j=0;j<=len-1;j++){
c=extract[j];
if(c==argument){
if(j-1>=0){
if(islower(extract[j-1])==0){
if(j+1<=len){
if(islower(extract[j-1])==0){
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
else{
expression[k]=c;
k++;
}
}
else{
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
}
else{
expression[k]=c;
k++;
}
}
else if(j+1<=len){
if(islower(extract[j-1])==0){
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
else{
expression[k]=c;
k++;
}
}
}
else{
expression[k]=c;
k++;
}
}
expression[k]='\0';
a=a*analyze(expression,err);
}
ssp--;
return(a);
}
double sigma(int start,int end,char expression[],int *err) /* Σ(総和) */
{
double a;
int i,j,k,l,len;
char c,argument,extract[256],number[10];
if(start>end){
printf("Error! Start value larger than end value");
exit(0);
}
ssp++;
argument=(char)('a'+ssp-1);
strcpy(extract,expression);
a=0.0;
for(i=start;i<=end;i++){
itoa(i,number,10);
k=0;
len=strlen(extract);
if(len==0){
printf("Error! Illeagal parameter");
exit(8);
}
for(j=0;j<=len-1;j++){
c=extract[j];
if(c==argument){
if(j-1>=0){
if(islower(extract[j-1])==0){
if(j+1<=len){
if(islower(extract[j-1])==0){
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
else{
expression[k]=c;
k++;
}
}
else{
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
}
else{
expression[k]=c;
k++;
}
}
else if(j+1<=len){
if(islower(extract[j-1])==0){
l=k;
c=number[k-l];
while(c!='\0'){
expression[k]=c;
k++;
c=number[k-l];
}
}
else{
expression[k]=c;
k++;
}
}
}
else{
expression[k]=c;
k++;
}
}
expression[k]='\0';
a=a+analyze(expression,err);
}
ssp--;
return(a);
}
double sinc(double x) /* sinc関数 */
{
double a,pai;
if(x==0)
a=1.0;
else{
pai=3.1415926535897932384626433832795028841971693;
a=sin(pai*x)/(pai*x);
}
return(a);
}
double pulse(double x) /* 単パルス関数 */
{
double a;
if(x>=-0.5 && x<=0.5)
a=1;
else
a=0;
return(a);
}
double triangle(double x) /* 三角波関数 */
{
double a,p,s,pai;
pai=3.1415926535897932384626433832795028841971693;
s=1.0;
a=0;
p=pai/2;
if(x<0){
s=-1;
x=-x;
}
x=x-2*pai*floor(x/(2*pai));
if(x>=0 && x<=p)
a=x/p;
else if(x>p && x<=pai+p)
a=-x/p+2;
else if(x>pai+p && x<=2*pai)
a=x/p-4;
a=a*s;
return(a);
}
double takevalue(char expression[],int *point,int *err) /* 値を取ってくる */
{
double a,b,sgn;
int i,j,k,l,len;
char c,func[10],extract[256];
static char *fnc[]={
"abs",
"acos",
"asin",
"atan",
"ceil",
"cos",
"cosh",
"exp",
"floor",
"log",
"log2",
"log10",
"sin",
"sinh",
"sqrt",
"tan",
"tanh",
"pai",
"sigma",
"sinc",
"pulse",
"pow",
"triangle"
};
static char *con[]={
"pai",
"e"
};
a=0;
i=0;
c=expression[i];
if(c=='-' || c=='+'){ /* 単項演算子のとき */
sgn=1.0;
if(c=='-') sgn=-1.0;
i++;
*point=*point+1;
len=strlen(expression);
strcpy(extract,(char *)prtcpy(expression,i,len));
a=sgn*takevalue(extract,point,err);
}
else if(c=='('){ /* ”(”のとき */
i++;
j=next(expression,i)-1;
strcpy(extract,(char *)prtcpy(expression,i,j));
a=analyze(extract,err);
*point=*point+j+2;
}
else if(isdigit(c)!=0 || c=='.'){ /* 数字のとき */
j=0;
extract[j]=c;
j++;
c=expression[j];
while(isdigit(c)!=0 || c=='.' || c=='d' || c=='D' || c=='e' || c=='E'){
extract[j]=c;
j++;
if(c=='d' || c=='D' || c=='e' || c=='E'){
c=expression[j];
if(isdigit(c)!=0 || c=='+' || c=='-'){
extract[j]=c;
j++;
}
else{
printf("Error! Illeagal value declaration");
exit(9);
}
}
c=expression[j];
}
extract[j]='\0';
a=atof(extract);
*point=*point+j;
}
else if(islower(c)!=0){ /* アルファベットのとき */
j=0;
func[j]=c;
j++;
c=expression[j];
while(isalnum(c)!=0){
func[j]=c;
j++;
if(j>9){
printf("Error! Illeagal function name");
exit(9);
}
c=expression[j];
}
func[j]='\0';
i=j;
if(c!='('){ /* 定数 */
if(strcmp(func,con[0])==0)
a=3.1415926535897932384626433832795028841971693;
else if(strcmp(func,con[1])==0)
a=2.7182818284590452353602874713526624977572;
else{
printf("Error! Illeagal constant name");
exit(10);
}
*point=*point+j;
}
else{ /* 関数 */
i++;
j=next(expression,i)-1;
strcpy(extract,(char *)prtcpy(expression,i,j));
if(strcmp(func,fnc[17])!=0 && strcmp(func,fnc[18])!=0 && strcmp(func,fnc[21])!=0)
a=analyze(extract,err);
else{ /* Π、Σ、powのとき */
strcpy(expression,extract);
len=strlen(expression);
k=0;
l=0;
c=expression[k];
while(c!=',' && l<=len){
extract[l]=c;
l++;
c=expression[l];
}
extract[l]='\0';
if(l>len){
printf("Error! Illeagal parameter");
exit(1);
}
a=analyze(extract,err);
k=l+1;
l=0;
c=expression[k];
while(c!=',' && k+l<=len){
extract[l]=c;
l++;
c=expression[k+l];
}
extract[l]='\0';
k=k+l+1;
if(strcmp(func,fnc[21])!=0){
if(k>len){
printf("Error! Illeagal parameter");
exit(2);
}
b=analyze(extract,err);
for(l=k;l<=len;l++){
extract[l-k]=expression[l];
}
extract[len-k+1]='\0';
}
else
b=analyze(extract,err);
}
*point=*point+j+2;
if(strcmp(func,fnc[0])==0)
a=fabs(a);
else if(strcmp(func,fnc[1])==0)
a=acos(a);
else if(strcmp(func,fnc[2])==0)
a=asin(a);
else if(strcmp(func,fnc[3])==0)
a=atan(a);
else if(strcmp(func,fnc[4])==0)
a=ceil(a);
else if(strcmp(func,fnc[5])==0)
a=cos(a);
else if(strcmp(func,fnc[6])==0)
a=cosh(a);
else if(strcmp(func,fnc[7])==0)
a=exp(a);
else if(strcmp(func,fnc[8])==0)
a=floor(a);
else if(strcmp(func,fnc[9])==0){
if(a<=0){
*err=1;
a=1e300;
}
else
a=log(a);
}
else if(strcmp(func,fnc[10])==0){
if(a<=0){
*err=1;
a=1e300;
}
else
a=log(a)/log(2);
}
else if(strcmp(func,fnc[11])==0){
if(a<=0){
*err=1;
a=1e300;
}
else
a=log10(a);
}
else if(strcmp(func,fnc[12])==0)
a=sin(a);
else if(strcmp(func,fnc[13])==0)
a=sinh(a);
else if(strcmp(func,fnc[14])==0)
a=sqrt(a);
else if(strcmp(func,fnc[15])==0)
a=tan(a);
else if(strcmp(func,fnc[16])==0)
a=tanh(a);
else if(strcmp(func,fnc[17])==0)
a=pai((int)a,(int)b,extract,err);
else if(strcmp(func,fnc[18])==0)
a=sigma((int)a,(int)b,extract,err);
else if(strcmp(func,fnc[19])==0)
a=sinc(a);
else if(strcmp(func,fnc[20])==0)
a=pulse(a);
else if(strcmp(func,fnc[21])==0){
if(a<0 && b!=floor(b))
a=0;
else
a=pow(a,b);
}
else if(strcmp(func,fnc[22])==0)
a=triangle(a);
else{
printf("Error! Illeagal function name");
exit(11);
}
}
}
else{
printf("Error! Illeagal syntax");
exit(12);
}
return(a);
}
int level(char operater) /* 二項演算子の優先順位 */
{
int i,l;
char level[6]={'^','*','/','%','+','-'};
l=0;
for(i=0;i<=5;i++){
if(operater==level[i]){
if(i==0) l=0;
else if(i==1 || i==2 || i==3) l=1;
else if(i==4 || i==5) l=2;
break;
}
}
return(l);
}
double biterm(char expression[],double a,int *point,int lev,int *err) /* 二項演算 */
{
int i,j,k,len,lv;
double b,d,s;
char c,extract[256];
d=0;
s=1.0;
i=0;
len=strlen(expression);
c=expression[i];
lv=level(c);
if(lv<lev) lv=lev;
i++;
k=*point;
*point=*point+1;
strcpy(extract,(char *)prtcpy(expression,i,len));
strcpy(expression,extract);
j=*point;
switch(c){
case '^':{
b=takevalue(expression,point,err);
i=i+*point-j-1;
if(i+1<=len-1){
c=expression[i];
if(lv>level(c)){
if(a<0 && b!=floor(b))
b=0;
else
b=pow(a,b);
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
d=biterm(extract,b,point,lv,err);
}
else
if(a<0 && b!=floor(b))
d=0;
else
d=pow(a,b);
}
else
d=pow(a,b);
} break;
case '*':{
b=takevalue(expression,point,err);
i=i+*point-j-1;
if(i+1<=len-1){
c=expression[i];
if(lv>level(c)){
if(c=='^'){
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
b=biterm(extract,b,point,lv,err);
d=a*b;
}
else{
b=a*b;
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
d=biterm(extract,b,point,lv,err);
}
}
else
d=a*b;
}
else
d=a*b;
} break;
case '/':{
b=takevalue(expression,point,err);
i=i+*point-j-1;
if(i+1<=len-1){
c=expression[i];
if(lv>level(c)){
if(c=='^'){
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
b=biterm(extract,b,point,lv,err);
if(b==0){
*err=1;
d=1e300;
}
else
d=a/b;
}
else{
if(b==0){
*err=1;
d=1e300;
}
else
b=a/b;
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
d=biterm(extract,b,point,lv,err);
}
}
else{
if(b==0){
*err=1;
d=1e300;
}
else
d=a/b;
}
}
else{
if(b==0){
*err=1;
d=1e300;
}
else
d=a/b;
}
} break;
case '%':{
b=takevalue(expression,point,err);
i=i+*point-j-1;
if(i+1<=len-1){
c=expression[i];
if(lv>level(c)){
if(c=='^'){
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
b=biterm(extract,b,point,lv,err);
d=fmod(a,b);
}
else{
b=fmod(a,b);
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
d=biterm(extract,b,point,lv,err);
}
}
else
d=fmod(a,b);
}
else
d=fmod(a,b);
} break;
case '-':s=-1.0;
case '+':{
b=takevalue(expression,point,err);
i=i+*point-j-1;
if(i+1<=len-1){
c=expression[i];
if(lv>level(c)){
strcpy(extract,(char *)prtcpy(expression,i,len));
*point=k+i+1;
b=biterm(extract,b,point,lv,err);
}
}
d=a+s*b;
} break;
default:{
printf("Error! Illeagal operater");
exit(13);
}
}
return(d);
}
double analyze(char expression[],int *err) /* メイン部分 */
{
int len,point; /* point:与えられた数式での位置 */
double a;
char extract[256];
strcpy(expression,(char *)spacefilter(expression));
len=strlen(expression);
point=1;
a=takevalue(expression,&point,err);
while(point<=len){
strcpy(extract,(char *)prtcpy(expression,point-1,len));
a=biterm(extract,a,&point,0,err);
}
return(a);
}
void main(int argc,char *argv[])
{
double a;
int err;
char expression[256];
err=0;
strcpy(expression,argv[1]);
if(argc!=2){
printf("\ncal 式\nの形式で入力 (例 cal 10*(2^8-1))\n");
exit(0);
}
a=analyze(argv[1],&err);
if(err!=0)
printf("\n演算中にエラーが発生しました。\n");
printf("\n%s=%17.15f\n指数形式 =%23.15e\n",expression,a,a);
}